3.3 UDP
前面已经无数次提及过,用户数据报协议(UDP)是一种 无连接的、简单的 传输层协议,其基本只对网络层 IP 协议做了最低限度的拓展,即提供多路复用与多路分解,和简单的差错检测。这也表明 UDP 与 IP 一样是一个 尽力而为 的服务,传送的报文段可能发生丢失、乱序等问题,也没有 TCP 的拥塞控制、流量控制等多余的功能。因此 UDP 会简单的以尽可能快的速率发送数据,这有可能导致网络核心进入拥塞状态,导致路由器大量丢弃分组,甚至挤垮同样在该链路上运行的 TCP 连接。
然而,没有多余功能的 UDP 也享受到了一些轻量级的好处:
- 无需建立连接与维护连接状态,不会引入建立连接状态需要的时延,也无需添加并跟踪为了维护连接需要的参数。
- 能够更加精细地控制发送什么数据与何时发送数据。
- 分组首部开销小。UDP 的头部开销仅有 8 字节。与之相比,TCP 的头部开销为 20 字节。
如果有应用既希望享受到 UDP 开销小带来的相对而言更高效的数据传送,又需要保证可靠的数据传输或其它功能,则需要应用自己在 应用层 实现相应的协议与规定。例如接下来在 3.8 节将要介绍的 QUIC。
UDP 的 8 字节头部分为 4 个字段,每个字段两字节,依次为:
- 源端口号
- 目标端口号
- 分组长度(包括头部的 8 字节,单位为字节)
- 报文段校验和
报文段校验和的计算原理如下,具体见:
发送方以 2 字节为单位 将报文段的数据部分逐个加在一起得到一个和,求和过程中如果发生了最高位的进位,该进位被 回滚加到最低位上。得到的这个和取 反码 即得到 UDP 校验和。
接收方收到报文后,将整个报文(包括校验和)同样以 2 字节为单位以同样的求和方式加在一起,只有当最终结果为 0xFFFF 时,可以认为该报文通过了校验。如果该报文没有通过校验,UDP 会依据协议规定要么直接丢弃该报文段要么在将该报文段交给应用程序的同时发出警告。然而 UDP 对于差错的恢复是无能为力的。
通过校验不等于数据无错!
通过了校验并不代表接收到的数据就是发送方原原本本发出来的数据。存在这样的可能:报文内出现了一些比特差错,但这些差错刚好使得报文仍然能通过校验。这种假阴性的错误被称作残存错误。